package cnpm.controller;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import cnpm.dto.DetailEmployeeDTO;
import cnpm.dto.UserDTO;
import cnpm.entity.Contract;
import cnpm.entity.Employee;
import cnpm.entity.Insurance;
import cnpm.service.BankService;
import cnpm.service.BrandBankService;
import cnpm.service.ContractService;
import cnpm.service.DepartmentService;
import cnpm.service.EmployeeService;
import cnpm.service.InsuranceService;
import cnpm.service.LiteracyService;
import cnpm.service.NationalityService;
import cnpm.service.OfficeService;
import cnpm.service.UserService;

/**
 * Servlet implementation class DetailEmployeeController
 */
@WebServlet("/DetailEmployeeController.do")
public class DetailEmployeeController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final int THRESHOLD_SIZE 	= 1024 * 1024 * 3; 	// 3MB
	private static final int MAX_FILE_SIZE 		= 1024 * 1024 * 40; // 40MB
	private static final int MAX_REQUEST_SIZE 	= 1024 * 1024 * 50; // 50MB
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DetailEmployeeController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		String action = request.getParameter("action");
		if(action.equals("detail")){
			getDetail(request, response);
		}
		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_detail.jsp");
		dispatcher.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		String action = request.getParameter("action");
		if(action.equals("updateEmployee")){
			updateEmployee(request, response);
		}else if(action.equals("deleteContract")){
			deleteContract(request, response);
		}else if(action.equals("deleteInsurance")){
			deleteInsurance(request, response);
		}else if(action.equals("detailContract")){
			detailContract(request, response);
		}else if(action.equals("detailInsurance")){
			detailInsurance(request, response);
		}else if(action.equals("updateContract")){
			updateContract(request, response);
		}else if(action.equals("updateInsurance")){
			updateInsurance(request, response);
		}
	}
	
	private void getDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		EmployeeService empS = (EmployeeService) context.getBean("employeeService");
		ContractService contractS = (ContractService) context.getBean("contractService");
		InsuranceService insuranceS = (InsuranceService) context.getBean("insuranceService");
		UserService userS = (UserService) context.getBean("userService");
		
		Employee employee = empS.getEmployeeByID(request.getParameter("employeeID"));
		
		DetailEmployeeDTO detail = new DetailEmployeeDTO();
		detail.setEmployee(employee);
		detail.setContracts(contractS.getAllContract(employee));
		detail.setInsurances(insuranceS.getAllInsurance(employee));
		detail.setUserCreate(userS.getUser(employee.getUserCreate()));
		detail.setUpdate(false);
		detail.setError(false);
		detail.setErrorEmail(false);
		detail.setErrorPhone(false);
		detail.setErrorIDCard(false);
		detail.setErrorAccountBank(false);

		if(employee.getUserUpdate() != null){
			detail.setUserUpdate(userS.getUser(employee.getUserUpdate()));
		}else{
			detail.setUserUpdate(null);
		}
		
		if(employee.getNationality() == null){
			detail.setNationality(0);
		}else{
			detail.setNationality(employee.getNationality().getNationalityID());
		}
		
		if(employee.getLiteracy() == null){
			detail.setLiteracy(0);
		}else{
			detail.setLiteracy(employee.getLiteracy().getLiteracyID());
		}
		request.setAttribute("DetailEmployees", detail);
	}
	
	@SuppressWarnings("rawtypes")
	private void updateEmployee(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String fileName = "";
		boolean femail = true;
		boolean fphone = true;
		boolean fidCard = true;
		boolean faccount = true;
		Map<String,String> model = new LinkedHashMap<String, String>();
		// checks if the request actually contains upload file
		if (!ServletFileUpload.isMultipartContent(request)) {
			PrintWriter writer = response.getWriter();
			writer.println("Request does not contain upload data");
			writer.flush();
			return;
		}
		// configures upload settings
		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setSizeThreshold(THRESHOLD_SIZE);
		factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
		
		ServletFileUpload upload = new ServletFileUpload(factory);
		upload.setFileSizeMax(MAX_FILE_SIZE);
		upload.setSizeMax(MAX_REQUEST_SIZE);
		
		// constructs the directory path to store upload file
		String uploadPath = getServletContext().getRealPath("/upload");
		// creates the directory if it does not exist
		File uploadDir = new File(uploadPath);
		if (!uploadDir.exists()) {
			uploadDir.mkdir();
		}
		
		try {
			// parses the request's content to extract file data
			List formItems = upload.parseRequest(request);
			Iterator iter = formItems.iterator();
			// iterates over form's fields
			while (iter.hasNext()) {
				FileItem item = (FileItem) iter.next();
				if(item.isFormField()){			
					String name = item.getFieldName();
				    String value = item.getString();
				    model.put(name, value);
				}
				// processes only fields that are not form fields
				else{
					String  filePathStored = getServletContext().getInitParameter("imagePath");
					fileName = new File(item.getName()).getName();
					if(!fileName.equals("")){
						String filePath = filePathStored + File.separator + fileName;					
						File storeFile = new File(filePath);
						item.write(storeFile);
					}
				}
			}
		} catch (Exception ex) {
			ex.getMessage();
		}
		
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		NationalityService nationalityS = (NationalityService) context.getBean("nationalityService");
		LiteracyService literacyS = (LiteracyService) context.getBean("literacyService");
		DepartmentService deptS = (DepartmentService) context.getBean("departmentService");
		BankService bankS = (BankService) context.getBean("bankService");
		BrandBankService brandS = (BrandBankService) context.getBean("brandBankService");
		OfficeService officeS = (OfficeService) context.getBean("officeService");
		EmployeeService empS = (EmployeeService) context.getBean("employeeService");
		ContractService contractS = (ContractService) context.getBean("contractService");
		InsuranceService insuranceS = (InsuranceService) context.getBean("insuranceService");
		UserService userS = (UserService) context.getBean("userService");
		
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar cal = Calendar.getInstance();
		
		UserDTO user = (UserDTO)request.getSession().getAttribute("User");
		
		Employee currentEmployee = empS.getEmployeeByID(request.getParameter("employeeID"));
		
		if(!model.get("empEmail").equals(currentEmployee.getEmail())){
			if(empS.isExitEmail(model.get("empEmail"))){
				femail= false;
			}
		}
		if(!model.get("empIDCard").equals(currentEmployee.getIndentityCard())){
			if(empS.isExitIndentityCard(model.get("empIDCard"))){
				fidCard= false;
			}
		}
		
		if(!model.get("empPhone").equals(currentEmployee.getPhone())){
			if(empS.isExitPhone(model.get("empPhone"))){
				fphone= false;
			}
		}
		
		if(!model.get("empAccountBank").equals(currentEmployee.getAccountBank())){
			if(empS.isExitAccountBank(model.get("empAccountBank"), bankS
					.getBankByID(Integer.parseInt(model.get("empBank"))))){
				faccount= false;
			}
		}
		
		Employee emp = new Employee();
		if(!fileName.equals("")){
			emp.setImage("image/upload/"+fileName);
		}else{
			emp.setImage(currentEmployee.getImage());
		}
		emp.setEmployeeID(currentEmployee.getEmployeeID());
		emp.setFirstName(model.get("empFirstName"));
		emp.setBirthdate(model.get("empBirthDate"));
		emp.setNationality(nationalityS.getNationalityByID(Integer.parseInt(model.get("empNationality"))));
		emp.setNaviteLand(model.get("empNativeLand"));
		emp.setEmail(model.get("empEmail"));
		emp.setIndentityCard(model.get("empIDCard"));
		emp.setLiteracy(literacyS.getLiteracyByID(Integer.parseInt(model.get("empLiteracy"))));
		emp.setDepartment(deptS.getDepartmentByID(Integer.parseInt(model.get("empDepartment"))));
		emp.setTitle(model.get("empTitle"));
		emp.setLastName(model.get("empLastName"));
		emp.setGender(Boolean.parseBoolean(model.get("empGender")));
		emp.setMaritalStatus(Boolean.parseBoolean(model.get("empMarital")));
		emp.setCurrentAddress(model.get("empCurrentAddress"));
		emp.setPhone(model.get("empPhone"));
		emp.setBank(bankS.getBankByID(Integer.parseInt(model.get("empBank"))));
		emp.setBrandBank(brandS.getBrandBak(Integer.parseInt(model.get("empBrandBank"))));
		emp.setAccountBank(model.get("empAccountBank"));
		emp.setOffice(officeS.getOffice(Integer.parseInt(model.get("empOffice"))));
		emp.setUserUpdate(user.getUsername());
		emp.setUpdateDate(dateFormat.format(cal.getTime()));
		emp.setUserCreate(currentEmployee.getUserCreate());
		emp.setCreateDate(currentEmployee.getCreateDate());
		
		if(femail && fphone && fidCard && faccount){
			if(empS.saveOrUpdateEmployee(emp) ){
				DetailEmployeeDTO detail = new DetailEmployeeDTO();
				detail.setEmployee(emp);
				detail.setContracts(contractS.getAllContract(emp));
				detail.setInsurances(insuranceS.getAllInsurance(emp));
				detail.setUserCreate(userS.getUser(currentEmployee.getUserCreate()));
				detail.setUserUpdate(userS.getUser(emp.getUserUpdate()));
				detail.setUpdate(true);
				detail.setError(false);
				detail.setErrorEmail(false);
				detail.setErrorPhone(false);
				detail.setErrorIDCard(false);
				detail.setErrorAccountBank(false);
				
				if(emp.getNationality() == null){
					detail.setNationality(0);
				}else{
					detail.setNationality( emp.getNationality().getNationalityID());
				}
				
				if(emp.getLiteracy() == null){
					detail.setLiteracy(0);
				}else{
					detail.setLiteracy(emp.getLiteracy().getLiteracyID());
				}
				
				request.setAttribute("DetailEmployees", detail);
				RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_detail.jsp");
				dispatcher.forward(request, response);
			}else{
				RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_add_error.jsp");
				dispatcher.forward(request, response);
			}
		}else{
			emp.setUpdateDate(currentEmployee.getUpdateDate());
			
			DetailEmployeeDTO detail = new DetailEmployeeDTO();
			detail.setEmployee(emp);
			detail.setContracts(contractS.getAllContract(emp));
			detail.setInsurances(insuranceS.getAllInsurance(emp));
			detail.setUserCreate(userS.getUser(currentEmployee.getUserCreate()));
			detail.setUserUpdate(userS.getUser(currentEmployee.getUserUpdate()==null?"":currentEmployee.getUserUpdate()));
			detail.setUpdate(false);
			detail.setError(true);
			
			if(emp.getNationality() == null){
				detail.setNationality(0);
			}else{
				detail.setNationality( emp.getNationality().getNationalityID());
			}
			
			if(emp.getLiteracy() == null){
				detail.setLiteracy(0);
			}else{
				detail.setLiteracy(emp.getLiteracy().getLiteracyID());
			}
			
			if(!femail){
				detail.setErrorEmail(true);
			}else{
				detail.setErrorEmail(false);
			}
			
			if(!fphone){
				detail.setErrorPhone(true);
			}else{
				detail.setErrorPhone(false);
			}
			
			if(!fidCard){
				detail.setErrorIDCard(true);
			}else{
				detail.setErrorIDCard(false);
			}
			
			if(!faccount){
				detail.setErrorAccountBank(true);
			}else{
				detail.setErrorAccountBank(false);
			}
			
			request.setAttribute("DetailEmployees", detail);
			RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_detail.jsp");
			dispatcher.forward(request, response);
		}
	}
	
	private void updateContract(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		ContractService contractS = (ContractService) context.getBean("contractService");
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar cal = Calendar.getInstance();
		
		UserDTO user = (UserDTO)request.getSession().getAttribute("User");
		
		Contract currentContract = contractS.getContractByID(request.getParameter("contractID"));
		Contract contract = new Contract();
		contract.setContractID(currentContract.getContractID());
		contract.setContractName(request.getParameter("contractName"));
		contract.setContractType(request.getParameter("contractType"));
		contract.setCreateDate(currentContract.getCreateDate());
		contract.setEmpContract(currentContract.getEmpContract());
		contract.setEndDate(request.getParameter("endDate"));
		contract.setRegDate(request.getParameter("regDate"));
		contract.setSalary(Integer.parseInt(request.getParameter("salary")));
		contract.setUpdateDate(dateFormat.format(cal.getTime()));
		contract.setUserCreate(currentContract.getUserCreate());
		contract.setUserUpdate(user.getUsername());
		if(contractS.saveOrUpdateContract(contract)){
			response.getWriter().write("Update contract "+currentContract.getContractID()+" success.");
		}else{
			response.getWriter().write("Update contract "+currentContract.getContractID()+" not success.");
		}
	}
	
	private void updateInsurance(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		InsuranceService insuranceS = (InsuranceService) context.getBean("insuranceService");
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar cal = Calendar.getInstance();
		
		UserDTO user = (UserDTO)request.getSession().getAttribute("User");
		
		Insurance currentInsurance = insuranceS.getInsuranceByID(request.getParameter("insuranceID"));
		Insurance insurance = new Insurance();
		insurance.setCreateDate(currentInsurance.getCreateDate());
		insurance.setEmpInsurance(currentInsurance.getEmpInsurance());
		insurance.setInsuranceID(currentInsurance.getInsuranceID());
		insurance.setInsurancType(request.getParameter("insuranceType"));
		insurance.setMoney(Integer.parseInt(request.getParameter("money")==""?"0":request.getParameter("money")));
		insurance.setPayForm(request.getParameter("payForm"));
		insurance.setRegDate(request.getParameter("insuranceRegDate"));
		insurance.setRegLocation(request.getParameter("insuranceRegPlace"));
		insurance.setUpdateDate(dateFormat.format(cal.getTime()));
		insurance.setUserCreate(currentInsurance.getUserCreate());
		insurance.setUserUpdate(user.getUsername());
		if(insuranceS.saveOrUpdateInsurance(insurance)){
			response.getWriter().write("Update contract "+currentInsurance.getInsuranceID()+" success.");
		}else{
			response.getWriter().write("Update contract "+currentInsurance.getInsuranceID()+" not success.");
		}
	}
	
	private void deleteContract(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		EmployeeService empS = (EmployeeService) context.getBean("employeeService");
		ContractService contractS = (ContractService) context.getBean("contractService");
		if(contractS.deleteContract(contractS.getContractByID(request.getParameter("contractID")))){
			response.getWriter().write("Delete contract "+request.getParameter("contractID")
					+" success~"+convertListContractToJson(contractS.getAllContract(empS
							.getEmployeeByID(request.getParameter("employeeID")))));
		}
	}
	
	private void deleteInsurance(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		EmployeeService empS = (EmployeeService) context.getBean("employeeService");
		InsuranceService insuranceS = (InsuranceService) context.getBean("insuranceService");
		if(insuranceS.deleteInsurance(insuranceS.getInsuranceByID(request.getParameter("insuranceID")))){
			response.getWriter().write("Delete insurance "+request.getParameter("insuranceID")
					+" success~"+convertListInsuranceToJson(insuranceS.getAllInsurance(empS
							.getEmployeeByID(request.getParameter("employeeID")))));
		}
	}
	
	private void detailContract(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		ContractService contractS = (ContractService) context.getBean("contractService");
		response.getWriter().write(convertContractToJson(contractS
				.getContractByID(request.getParameter("contractID"))));
	}
	
	private void detailInsurance(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		InsuranceService insuranceS = (InsuranceService) context.getBean("insuranceService");
		response.getWriter().write(convertInsuranceToJson(insuranceS
				.getInsuranceByID(request.getParameter("insuranceID"))));
	}
	
	private String convertListContractToJson(List<Contract> contracts){
		JsonObject jsonObj;
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonResponse = new JsonObject();
		for(Contract contract: contracts){
			jsonObj = new JsonObject();
			jsonObj.addProperty("contractID", contract.getContractID());
			jsonObj.addProperty("contractType", contract.getContractType());
			jsonObj.addProperty("contractName", contract.getContractName());
			jsonObj.addProperty("regDate", contract.getRegDate());
			jsonObj.addProperty("startDate", contract.getStartDate());
			jsonObj.addProperty("endDate", contract.getEndDate());
			jsonObj.addProperty("salary", contract.getSalary());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("Contracts", jsonArray);
		return String.valueOf(jsonResponse);
	}
	
	private String convertListInsuranceToJson(List<Insurance> insurances){
		JsonObject jsonObj;
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonResponse = new JsonObject();
		for(Insurance insurance: insurances){
			jsonObj = new JsonObject();
			jsonObj.addProperty("insuraceID", insurance.getInsuranceID());
			jsonObj.addProperty("insuraceType", insurance.getInsurancType());
			jsonObj.addProperty("regDate", insurance.getRegDate());
			jsonObj.addProperty("regPlace", insurance.getRegLocation());
			jsonObj.addProperty("payForm", insurance.getPayForm());
			jsonObj.addProperty("money", insurance.getMoney());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("Insurances", jsonArray);
		return String.valueOf(jsonResponse);
	}
	
	private String convertContractToJson(Contract contract){
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		UserService userS = (UserService) context.getBean("userService");
		
		JsonObject jsonObj = new JsonObject();
		JsonObject jsonResponse = new JsonObject();
		jsonObj.addProperty("contractID", contract.getContractID());
		jsonObj.addProperty("contractType", contract.getContractType());
		jsonObj.addProperty("contractName", contract.getContractName());
		jsonObj.addProperty("regDate", contract.getRegDate());
		jsonObj.addProperty("startDate", contract.getStartDate());
		jsonObj.addProperty("endDate", contract.getEndDate());
		jsonObj.addProperty("salary", contract.getSalary());
		jsonObj.addProperty("createDate", contract.getCreateDate());
		jsonObj.addProperty("userCreate", userS.getUser(contract.getUserCreate()).getFullname());
		if(contract.getUserUpdate() != null){
			jsonObj.addProperty("userUpdate", userS.getUser(contract.getUserUpdate()).getFullname());
		}else{
			jsonObj.addProperty("userUpdate", "No update");
		}
		if(contract.getUpdateDate() != null){
			jsonObj.addProperty("updateDate", contract.getUpdateDate());
		}else{
			jsonObj.addProperty("updateDate", "No Update");
		}
		jsonResponse.add("Contracts", jsonObj);
		return String.valueOf(jsonResponse);
	}
	
	private String convertInsuranceToJson(Insurance insurance){
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		UserService userS = (UserService) context.getBean("userService");
		
		JsonObject jsonObj = new JsonObject();
		JsonObject jsonResponse = new JsonObject();
		jsonObj.addProperty("insuranceID", insurance.getInsuranceID());
		jsonObj.addProperty("insuranceType", insurance.getInsurancType());
		jsonObj.addProperty("insuranceRegDate", insurance.getRegDate());
		jsonObj.addProperty("insuranceRegPlace", insurance.getRegLocation());
		jsonObj.addProperty("insurancePayForm", insurance.getPayForm());
		jsonObj.addProperty("insuranceMoney", insurance.getMoney());
		jsonObj.addProperty("createDate", insurance.getCreateDate());
		jsonObj.addProperty("userCreate", userS.getUser(insurance.getUserCreate()).getFullname());
		if(insurance.getUserUpdate() != null){
			jsonObj.addProperty("userUpdate", userS.getUser(insurance.getUserUpdate()).getFullname());
		}else{
			jsonObj.addProperty("userUpdate", "No update");
		}
		if(insurance.getUpdateDate() != null){
			jsonObj.addProperty("updateDate", insurance.getUpdateDate());
		}else{
			jsonObj.addProperty("updateDate", "No Update");
		}
		jsonResponse.add("Insurances", jsonObj);
		return String.valueOf(jsonResponse);
	}
}
